/**
 * @file ViewAdaptor_interface.h
 * @author Фетисов Михаил Вячеславович (fetisov.michael@yandex.ru)
 * @brief Объявления интерфейса адаптера представления документа.
 * @version 0.1
 * @date 2023-02-15
 *
 * @copyright MIT: Michael Fetisov, Anton Bushev
 *
 */
#ifndef simodo_shell_document_ViewAdaptor_interface_H
#define simodo_shell_document_ViewAdaptor_interface_H

#include "simodo/shell/Service.h"
#include "simodo/shell/document/DocumentAdaptor_interface.h"

#include <QWidget>
#include <QPair>

#include <memory>

QT_BEGIN_NAMESPACE
class QPrinter;
QT_END_NAMESPACE

namespace simodo::shell
{
    class Document_plugin;
    class ViewAdaptorLsp_interface;
    class ViewAdaptorFind_interface;
    class AdaptorModeling_interface;

/**
 * @brief Интерфейс адаптера представления документа.
 *
 * Адаптер представления документа является посредником между оболочкой и виджетом документа.
 *
 * @details
 * Оболочка делегирует адаптеру представления документа выполнение функций,
 * инициированных пользователем.
 *
 */
class ViewAdaptor_interface
{
public:
    virtual ~ViewAdaptor_interface() = default;

    /**
     * @brief Адаптер документа, с которым работает данное представление.
     *
     * @return указатель на адаптер документа
     */
    virtual std::shared_ptr<DocumentAdaptor_interface> document_adaptor() = 0;
    const std::shared_ptr<DocumentAdaptor_interface> document_adaptor() const
    {
        auto thi = const_cast<ViewAdaptor_interface *>(this);
        return thi->document_adaptor();
    }

    /**
     * @brief Виджет документа.
     *
     * @return виджет документа
     */
    virtual QWidget * document_widget() = 0;

    /**
     * @brief Плагин документа, создавший данный адаптер представления документа
     *
     * @return указатель на объект плагин а
     */
    virtual Document_plugin * plugin() = 0;

    /**
     * @brief Установка особенностей виджета.
     * Иногда настройки виджета, выполняемые в конструкторе слетают после размещения его в окне
     * документа. В этом случае можно их выполнить в этом методе, который вызывается после размещения.
     *
     * @param widget виджет, который нужно настроить
     */
    virtual void readyToWork(QWidget * widget) = 0;

    /**
     * @brief Копия виджета документа, которая работает с тем же адаптером документа.
     *
     * Данный метод используется оболочкой для реализации разделения документа на части (splitter).
     *
     * @attention Оболочка сама удалит полученный виджет при закрытии документа или в случае другой
     * необходимости.
     *
     * @return указатель на копию виджета
     */
    virtual QWidget * copyWidget() = 0;

    /**
     * @brief Загрузить файл по заданному пути.
     *
     * @deprecated Данный метод будет удалён из интерфейса из соображений безопасности.
     *
     * @param path полный путь к файлу
     * @return текст ошибки или пустая строка.
     */
    virtual QString loadFile(const QString &path) = 0;

    /**
     * @brief Установить режим только для чтения, не допускающий изменения документа.
     *
     */
    virtual void setReadOnly() = 0;

    /**
     * @brief Выполнить вывод документа на заданный принтер.
     *
     * @param printer принтер для печати
     */
    virtual void print(QPrinter * printer) = 0;

    /**
     * @brief Вырезать выделенный фрагмент документа в системный буфер обмена.
     *
     */
    virtual void cutFromDocument() = 0;

    /**
     * @brief Скопировать выделенный фрагмент документа в системный буфер обмена.
     *
     */
    virtual void copyFromDocument() = 0;

    /**
     * @brief Вставить содержимое системного буфера обмена в документ.
     *
     */
    virtual void pasteToDocument() = 0;

    /**
     * @brief Возвращает признак имеет ли документ выделенный фрагмент.
     *
     * @return true - выделенный фрагмент присутствует,
     * @return false - выделенный фрагмент отсутствует.
     */
    virtual bool hasSelection() = 0;

    /**
     * @brief Возвращает признак возможности сделать откат изменений.
     *
     * @return true - можно выполнить откат изменений,
     * @return false - откат изменений невозможен.
     */
    virtual bool hasUndo() = 0;

    /**
     * @brief Возвращает признак возможности повторения изменений.
     *
     * @return true - можно повторить изменения,
     * @return false - повтор изменений невозможен.
     */
    virtual bool hasRedo() = 0;

    /**
     * @brief Выполнить увеличение изображения документа.
     *
     */
    virtual void zoomIn() = 0;

    /**
     * @brief Выполнить уменьшение изображения документа.
     *
     */
    virtual void zoomOut() = 0;

    /**
     * @brief Установить стандартный размер изображения документа.
     *
     */
    virtual void zoomZero() = 0;

    /**
     * @brief Получение текущих координат курсора
     *
     * @return позиция в формате <вертикально,горизонтально>
     */
    virtual QPair<int,int> getLineCol() const = 0;

    /**
     * @brief Установка положения курсора.
     *
     * @param line_col позиция в формате <вертикально,горизонтально>
     */
    virtual void setLineCol(QPair<int,int> line_col) = 0;

    /**
     * @brief Приём данных
     *
     * @param data данные в структуре JSON
     * @return true - удалось интерпретировать и отобразить данные,
     * @return false - данные не удалось интерпретировать
     */
    virtual bool acceptData(const QJsonObject & data) = 0;

    /**
     * @brief Предоставление указателя на интерфейс клиента LSP
     * 
     * @return Указатель на интерфейс клиента LPS или nullptr, если работа с LSP не поддерживается
     */
    virtual ViewAdaptorLsp_interface * getLspInterface() = 0;

    /**
     * @brief Предоставление указателя на интерфейс поиска
     * 
     * @return Указатель на интерфейс поиска или nullptr, если поиск не поддерживается
     */
    virtual ViewAdaptorFind_interface * getFindInterface() = 0;

    /**
     * @brief Предоставление указателя на интерфейс моделирования
     * 
     * @return Указатель на интерфейс моделирования или nullptr, если интерфейс моделирования не 
     * поддерживается
     */
    virtual AdaptorModeling_interface * getModelingInterface() = 0;

    /**
     * @brief Вызывается перед выполнением закрытия окна
    */
    virtual void nearToClose() = 0;
};

}

#endif // simodo_shell_document_ViewAdaptor_interface_H